package drds.plus.executor.data_node_executor.spi;


import drds.plus.common.lifecycle.AbstractLifecycle;
import drds.plus.common.model.Application;
import drds.plus.common.model.DataNode;
import drds.plus.executor.repository.Repository;
import drds.plus.executor.repository.RepositoryNameToRepositoryMap;
import drds.plus.sql_process.abstract_syntax_tree.configuration.parse.ApplicationParser;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;

import java.util.HashMap;
import java.util.Map;


@Slf4j
public class DataNodeExecutorManager extends AbstractLifecycle {


    private final Map<String, DataNodeExecutor> dataNodeIdToDataNodeExecutorMap = new HashMap<String, DataNodeExecutor>();
    private String applicationId;

    private Application application;
    private Map cp;


    private RepositoryNameToRepositoryMap repositoryTypeToRepositoryMap;

    public DataNodeExecutorManager(String applicationId) {
        this.applicationId = applicationId;
        this.repositoryTypeToRepositoryMap = new RepositoryNameToRepositoryMap();
    }

    public DataNodeExecutorManager(String applicationId, Map cp) {
        this(applicationId);
        this.cp = cp;
    }

    protected void doInit() {
        this.application = initApplication();
        application.setId(applicationId);
    }

    private Application initApplication() {
        String data = null;
        Application application = ApplicationParser.parse(data);
        return application;
    }

    protected void doDestroy() throws RuntimeException {
        Map<String, Repository> repositoryNameToRepositoryMap = this.repositoryTypeToRepositoryMap.getRepositoryTypeToRepositoryMap();
        for (Repository repository : repositoryNameToRepositoryMap.values()) {
            repository.destroy();
        }

    }

    /**
     * 子类和上层实现都是通过该类切换具体的DataNodeExecutor
     */
    public DataNodeExecutor getDataNodeExecutor(String dataNodeId) {
        DataNodeExecutor dataNodeExecutor = dataNodeIdToDataNodeExecutorMap.get(dataNodeId);
        if (dataNodeExecutor == null) {
            DataNode dataNode = application.getDataNode(dataNodeId);
            if (dataNode != null) {
                synchronized (dataNodeIdToDataNodeExecutorMap) {
                    dataNodeExecutor = dataNodeIdToDataNodeExecutorMap.get(dataNodeId);
                    if (dataNodeExecutor == null) {
                        return createDataNodeExecutor(dataNode);
                    } else {
                        return dataNodeIdToDataNodeExecutorMap.get(dataNodeId);
                    }
                }
            }
        }

        return dataNodeExecutor;
    }

    /**
     * 指定Group配置，创建一个GroupExecutor
     */
    public DataNodeExecutor createDataNodeExecutor(DataNode dataNode) {
        Repository repository = repositoryTypeToRepositoryMap.getRepository(dataNode.getRepositoryType().name(), application.getProperties(), cp);
        DataNodeExecutor dataNodeExecutor = repository.getDataNodeExecutor(dataNode);
        put(dataNode.getId(), dataNodeExecutor);
        return dataNodeExecutor;
    }

    public DataNodeExecutor put(String dataNodeId, DataNodeExecutor dataNodeExecutor) {
        if (dataNodeIdToDataNodeExecutorMap.containsKey(dataNodeId)) {
            throw new IllegalArgumentException("datanode columnName is already exists . datanode columnName : " + dataNodeId + " . map " + dataNodeIdToDataNodeExecutorMap);
        }
        return dataNodeIdToDataNodeExecutorMap.put(dataNodeId, dataNodeExecutor);
    }

    public Application getApplication() {
        return this.application;
    }


    public RepositoryNameToRepositoryMap getRepositoryTypeToRepositoryMap() {
        return repositoryTypeToRepositoryMap;
    }


    public Logger log() {
        return log;
    }
}
